import * as os from 'os'
import * as fs from 'fs'
import * as path from 'path'
import { shouldBeHiddenSync } from 'hidefile'
import iconPromise from 'icon-promise'
import { getIconForFile, getIconForFolder } from 'vscode-icons-js'

type FileList = (Directory | File)[]
type Directory = {
  name: string
  path: string
  mtime: Date
  type: string
  atime: Date
  isHidden: boolean
}
type File = {
  name: string
  path: string
  icon?: string
  mtime: Date
  type: string
  size: string
  atime: Date
  isHidden: boolean
}
export const list = async (dirPath: string): Promise<FileList> => {
  try {
    const dir = fs.readdirSync(dirPath, {
      withFileTypes: true,
    })
    const dirList: Directory[] = []
    const fileList: File[] = []
    for (const item of dir) {
      try {
        const fullPath = path.resolve(dirPath, item.name)
        const ext = path.parse(item.name).ext
        const isDirectory = item.isDirectory()
        const isFile = item.isFile()
        const stat = fs.statSync(fullPath, {
          bigint: true,
        })
        const fileInfo: Directory | File = {
          name: item.name,
          path: fullPath,
          mtime: stat.mtime,
          type: isDirectory ? 'dir' : ext,
          atime: stat.atime,
          size: stat.size.toString(),
          isHidden: shouldBeHiddenSync(fullPath),
        }
        if (isDirectory) {
          fileInfo.icon = '/icons/' + getIconForFolder(item.name)
        } else if (isFile) {
          if (ext === '.exe' && os.platform() === 'win32') {
            try {
              fileInfo.icon =
                'data:image/png;base64,' +
                (await iconPromise.getIcon(fullPath)).Base64ImageData
            } catch (error) {
              console.error(error)
            }
          } else fileInfo.icon = '/icons/' + getIconForFile(item.name)
        }
        if (isDirectory) {
          dirList.push(fileInfo)
        } else if (isFile) {
          fileList.push(fileInfo)
        }
      } catch (error) {
        console.error(error)
      }
    }
    return dirList.concat(fileList)
  } catch (error) {
    return error
  }
}
